package workerwithdb.managers;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import workerwithdb.dao.HibernateDAOGarage;
import workerwithdb.dao.HibernateDAOMaster;
import workerwithdb.dao.HibernateDAOOperation;
import workerwithdb.dao.HibernateDAOOrder;
import workerwithdb.dao.HibernateDAOUser;
import workerwithdb.hibernateutil.HibernateUtil;
import autoproperties.AutoProperties;
import autoservice.api.entitites.IGarage;
import autoservice.api.entitites.IMaster;
import autoservice.api.entitites.IOperation;
import autoservice.api.entitites.IOrder;
import autoservice.api.entitites.IUser;
import autoservice.api.entitites.OrderStatus;
import entitiesfactory.EntitiesFactory;
import exportimporterentities.ExportImportEntities;

public class DBManager {

	private HibernateDAOOrder daoOrder = new HibernateDAOOrder();
	private HibernateDAOGarage daoGarage = new HibernateDAOGarage();
	private HibernateDAOMaster daoMaster = new HibernateDAOMaster();
	private HibernateDAOUser daoUser = new HibernateDAOUser();
	private HibernateDAOOperation daoOperation = new HibernateDAOOperation();
	private HibernateUtil hibernateUtil = HibernateUtil.getInstance();
	private EntitiesFactory entitiesFactory = EntitiesFactory.getInstance();
	private AutoProperties autoProperties = AutoProperties.getInstance();
	private ExportImportEntities exportImportEntities = new ExportImportEntities();
	private static final String EMPTY_STRING = ""; 

	private Logger log = Logger.getLogger(DBManager.class);

	private Session getSession() {
		Session session = hibernateUtil.getSessionFactory().getCurrentSession();
		return session;
	}

	private Transaction getTransaction(Session session) {
		Transaction transaction = session.beginTransaction();
		return transaction;
	}

	private void exceptionActivity(Exception e, Transaction transaction) {
		log.error(e);
		transaction.rollback();
	}
	
	public void setOperation(String userLogin,String nameOperation,Date timeOperation){
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
			IOperation operation = (IOperation) entitiesFactory.getObject(IOperation.class);
			operation.setUserLogin(userLogin);
			operation.setNameOperation(nameOperation);
			operation.setTimeOperation(timeOperation);
			daoOperation.save(operation, session);
			transaction.commit();
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
	}

	public Boolean saveUser(String userName, String userLogin,
			String userPassword) {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			if (!(userLogin.equals(EMPTY_STRING) || userPassword.equals(EMPTY_STRING))) {

				IUser user = (IUser) entitiesFactory.getObject(IUser.class);
				user.setNameUser(userName);
				user.setLoginUser(userLogin);
				user.setPasswordUser(userPassword);
				daoUser.save(user, session);
				transaction.commit();
				return true;
			} else {
				return false;
			}
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return false;
		}
	}

	public String getAutorization(String login, String password) {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IUser user = daoUser.readUser(login, session);
			transaction.commit();
			if (user.getPasswordUser().equals(password)) {
				return user.getNameUser();
			} else {
				return null;
			}
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public Long getEmptyPlaces() throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			Long places = daoGarage.getEmptyGarage(session);
			transaction.commit();
			return places;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public IOrder getOrderByMaster(String masterName) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IOrder order = daoMaster.getOrderByMaster(masterName, session);
			transaction.commit();
			return order;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public IMaster getMasterByOrder(Integer orderNumber) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IMaster master = daoOrder.getMasterByOrder(orderNumber, session);
			transaction.commit();
			return master;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public Long getEmptyPlacesOnDate(Date date) throws Exception {
		Session session = getSession();
		Transaction transaction = session.beginTransaction();
		try {
			Long countGarage = daoGarage.getEmptyGaragesOnDate(date, session);
			Long countMaster = daoMaster.getEmptyMastersOnDate(date, session);
			transaction.commit();
			Long count = null;
			if (countGarage == 0 || countMaster == 0) {
				count = (long) 0;
			} else if (countMaster > countGarage) {
				count = countGarage;
			} else if (countMaster < countGarage) {
				count = countMaster;
			} else {
				count = countGarage;
			}
			return count;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public Date getNextFreeDate() throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			Date date = daoOrder.getNextFreeDate(session);
			transaction.commit();
			return date;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public List<IOrder> sortAllOrder(SortOrdersBy sortBy) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IOrder> listOrder = daoOrder.sortAllOrders(sortBy, session);
			transaction.commit();
			return listOrder;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public List<IMaster> sortMaster(SortMastersBy sortBy) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IMaster> listMaster = daoMaster.sortMasters(sortBy, session);
			transaction.commit();
			return listMaster;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public List<IOrder> sortMadingOrder(SortOrdersBy sortBy) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IOrder> listOrder = daoOrder.sortMadingOrders(sortBy, session);
			transaction.commit();
			return listOrder;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public List<IOrder> sortOrderByPeriod(OrderStatus ordSt, Date begin,
			Date end, SortOrdersBy sortBy) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IOrder> listOrder = daoOrder.sortOrdersByPeriod(begin, end,
					sortBy, ordSt.toString(), session);
			transaction.commit();
			return listOrder;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public Boolean addMaster(String masterName) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IMaster master = (IMaster) entitiesFactory.getObject(IMaster.class);
			master.setName(masterName);
			daoMaster.save(master, session);
			answer = true;
			transaction.commit();
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean deleteMaster(String masterName) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IMaster master = daoMaster.readMaster(masterName, session);
			daoMaster.delete(master, session);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean addGarage(Integer numberGarage) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			if (autoProperties.getGarageManager() == true) {
				IGarage garage = (IGarage) entitiesFactory
						.getObject(IGarage.class);
				garage.setNumber(numberGarage);
				daoGarage.save(garage, session);
				transaction.commit();
				answer = true;
			}
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean deleteGarage(Integer numberGarage) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			if (autoProperties.getGarageManager() == true) {
				IGarage garage = daoGarage.readGarage(numberGarage, session);
				daoGarage.delete(garage, session);
				transaction.commit();
				answer = true;
			}
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean addOrder(Integer orderNumber, Date fillingDate,
			Date deadlineDate, Date beginingDate, Integer price,
			String masterName, Integer numberGarage) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IOrder order = (IOrder) entitiesFactory.getObject(IOrder.class);
			IMaster master = daoMaster.readMaster(masterName, session);
			IGarage garage = daoGarage.readGarage(numberGarage, session);
			order.setNumber(orderNumber);
			order.setPrice(price);
			order.setBeginingDate(beginingDate);
			order.setDeadlineDate(deadlineDate);
			order.setFillingDate(fillingDate);
			order.setMaster(master);
			master.setEmployment(true);
			order.setGarage(garage);
			garage.setFullness(true);
			daoGarage.update(garage, session);
			daoMaster.update(master, session);
			daoOrder.save(order, session);
			;
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean markOrder(Integer numberOrder, OrderStatus orderStatus)
			throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IOrder order = daoOrder.readOrder(numberOrder, session);
			IMaster master = order.getMaster();
			IGarage garage = order.getGarage();
			master.setEmployment(false);
			garage.setFullness(false);
			order.setOrderStatus(orderStatus.toString());
			daoOrder.update(order, session);
			daoMaster.update(master, session);
			daoGarage.update(garage, session);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean shiftOrdersDeadlineDate(Date newDate, Integer numberOrder)
			throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			if (autoProperties.getPermissionShiftTimeOrder()) {
				IOrder order = daoOrder.readOrder(numberOrder, session);
				order.setDeadlineDate(newDate);
				daoOrder.update(order, session);
				answer = true;
				transaction.commit();
			}
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean cloneOrder(Integer number) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IOrder order = daoOrder.readOrder(number, session);
			IOrder clone = order.cloneOrder();
			Long numberClone = daoOrder.getMaxNumberOrder(session) + 1;
			String s = numberClone.toString();
			clone.setNumber(Integer.parseInt(s));
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean exportGarages(String path) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IGarage> garageList = daoGarage.getAll(session);
			exportImportEntities.ExportGarages(garageList, path);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean exportMasters(String path) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IMaster> masterList = daoMaster.getAll(session);
			exportImportEntities.ExportMasters(masterList, path);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean exportOrders(String path) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IOrder> orderList = daoOrder.getAll(session);
			exportImportEntities.ExportOrders(orderList, path);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean importGarages(String path) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			ArrayList<IGarage> garageList = exportImportEntities
					.ImportGarages(path);
			daoGarage.insertAllGarages(garageList, session);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean importMasters(String path) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			ArrayList<IMaster> masterList = exportImportEntities
					.ImportMasters(path);
			daoMaster.insertAllMasters(masterList, session);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	public Boolean importOrders(String orderPath, String masterPath,
			String garagePath) throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			ArrayList<IOrder> orderList = exportImportEntities.ImportOrders(
					orderPath, masterPath, garagePath);
			daoOrder.insertAllOrders(orderList, session);
			transaction.commit();
			answer = true;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
		}
		return answer;
	}

}